home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Mac-Source 1994 July
/
Mac-Source_July_1994.iso
/
C and C++
/
Compilers⁄Interps
/
kevoSource
/
recompile.c
< prev
next >
Wrap
Text File
|
1993-03-13
|
7KB
|
211 lines
/* Kevo -- a prototype-based object-oriented language */
/* (c) Antero Taivalsaari 1991-1993 */
/* Some parts (c) Antero Taivalsaari 1986-1988 */
/* recompile.c: Recompiler internals */
#include "global.h"
/*------------------------------------------------------------------------*/
/* These operations automatically rebind all the early bound references */
/* within an object when properties are CUT/COPY/PASTEd or redefined. */
/* rebind(): needed internally in the subsequent recompilation operations */
LIST* oldProps;
LIST* newProps;
void rebind(newObjectPtr, origObject, offset, target)
OBJECT** newObjectPtr;
OBJECT* origObject;
int offset;
OBJECT* target;
{
/* Duplicate the property (only once, however) */
if (!*newObjectPtr) {
*newObjectPtr = copyObject(origObject);
/* Add the recompilation information to the property lists */
addToList(oldProps, origObject);
addToList(newProps, *newObjectPtr);
}
/* Change the reference in the duplicate to point to the new property */
*((int*)(*newObjectPtr)->mfa + offset) = (int)target;
}
/* recompileProperty(): starting from a pair, rebind all the references to
the given old property to the current property.
This operation should be invoked when a property (normally a method)
is redefined.
*/
void recompileProperty(changedPair, oldProperty)
PAIR* changedPair;
OBJECT* oldProperty;
{
PAIR* thisPair = changedPair->sfa;
/*
Since each rebound property will cause a propagated effect
(that property will have to be subsequently rebound too),
we store the corresponding properties in dynamically growing
lists.
*/
oldProps = createList();
newProps = createList();
addToList(oldProps, oldProperty);
addToList(newProps, changedPair->ofa);
/* Walk through all the properties starting from the successor of 'changedPair' */
while (thisPair) {
OBJECT* thisObject = thisPair->ofa;
STORE* store = thisObject->mfa;
int size = thisObject->sfa;
OBJECT* newObject = NIL;
int offset;
/* Walk through all the slots in the current property */
for (offset = 0; offset < size; offset++) {
OBJECT* refObject = (OBJECT*)*((int*)store + offset);
int index;
/* Check if the referred property has been redefined */
if (index = findInList(oldProps, refObject))
rebind(&newObject, thisObject, offset, fetchFromList(newProps, index));
}
/* If the property was redefined, change the pair to refer to it */
if (newObject) {
thisPair->ofa = newObject;
fprintf(confile, " Method '%s' recompiled.\n", thisPair->nfa);
}
thisPair = thisPair->sfa;
}
deleteList(oldProps);
deleteList(newProps);
}
/* This operation is used internally to find the previous property */
/* with the given name starting from an arbitrary pair in a context */
PAIR* traverseThread(thePair, string)
PAIR* thePair;
char* string;
{
int thread = hash(string);
PAIR* prevPair;
PAIR* succPair;
PAIR* prevInThread;
PAIR* succInThread;
/* Use 'findSurroundings' to save efforts (is not the fastest possible, though) */
findSurroundings(thePair, thread, &prevPair, &succPair, &prevInThread, &succInThread);
/* Find the previous pair with the same name in the correct thread */
return(selfLookUp(prevInThread, string));
}
/* rebindContext(): starting from a pair, check the bindings of names
Each property should refer to the previous defined property with the
same name in its context.
This operation should be invoked when properties are CUT/COPY/PASTED
to/from an object. 'Oldcontext' must contain the original (unmodified)
context of the object.
*/
void rebindContext(fromPair, oldContext)
PAIR* fromPair;
CONTEXT* oldContext;
{
CONTEXT* thisContext = fromPair->cfa;
PAIR* thisPair = fromPair;
oldProps = createList();
newProps = createList();
/* Walk through all the properties starting from 'fromPair' */
while (thisPair) {
OBJECT* thisObject = thisPair->ofa;
STORE* store = thisObject->mfa;
int size = thisObject->sfa;
OBJECT* newObject = NIL;
int offset;
/* printf("Checking '%s'.\n", thisPair->nfa); */
/* Walk through all the slots in the current property */
for (offset = 0; offset < size; offset++) {
OBJECT* refObject = (OBJECT*)*((int*)store + offset);
PAIR* origPair = NIL;
PAIR* prevPair = NIL;
int index;
/* Check if binding must be updated */
/* Case 1: A new intervening property with the same name */
/* has been added between this and old pair? */
origPair = findNameInThis(thisContext, refObject);
if (origPair) {
/* printf(" Referring to '%s (%d)'.\n", origPair->nfa, refObject); */
prevPair = traverseThread(thisPair, origPair->nfa);
if (prevPair && prevPair != origPair) {
/* A new name has been added between the original and this pair */
/* -> rebind to 'prevPair' */
/* printf(" Rebinding reference to '%s' in '%s'.\n", origPair->nfa, thisPair->nfa); */
rebind(&newObject, thisObject, offset, prevPair->ofa);
}
}
/* Case 2: Try to bind the property using the same name that the property */
/* had in its old context (context from which the property was */
/* copied/pasted) */
else {
if (oldContext) {
/* Get the name to which the reference should be bound */
origPair = findNameInThis(oldContext, refObject);
if (origPair) {
/* printf(" *Referring to '%s (%d)'.\n", origPair->nfa, refObject); */
/* Using the name, find the possible corresponding property in new ctxt */
prevPair = traverseThread(thisPair, origPair->nfa);
if (prevPair) {
/* Rebind the reference to 'prevPair' */
/* printf(" *Rebinding a reference to '%s' in '%s'.\n", origPair->nfa, thisPair->nfa); */
rebind(&newObject, thisObject, offset, prevPair->ofa);
}
else {
fprintf(confile, "== Cannot rebind early bound call to '%s' in method '%s' ==\n",
origPair->nfa, thisPair->nfa);
}
}
}
}
/* Case 3: The referred property has been redefined as a result of previous changes */
if (!prevPair && (index = findInList(oldProps, refObject))) {
/* printf("Propagating a change.\n"); */
rebind(&newObject, thisObject, offset, fetchFromList(newProps, index));
}
}
/* If the property was changed, change the pair to refer to it */
if (newObject) {
thisPair->ofa = newObject;
fprintf(confile, " Method '%s' recompiled.\n", thisPair->nfa);
}
thisPair = thisPair->sfa;
}
deleteList(oldProps);
deleteList(newProps);
/* printf("Checking complete.\n"); */
}